package com.jwds.digital.bios.business.service.service.belt.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jwds.digital.bios.business.core.constants.BeltCloudConstant;
import com.jwds.digital.bios.business.core.infrastructure.dto.feign.FlowBasicReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltDayTargetHis;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltPerformanceMinute;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRouteTargetHis;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRouteTaskBeltDetail;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRouteTaskBeltMain;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRouteTaskDetail;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltRouteTaskMain;
import com.jwds.digital.bios.business.core.infrastructure.telegram.BeltRouteBelongData;
import com.jwds.digital.bios.business.core.infrastructure.vo.feign.FlowBasicRespVO;
import com.jwds.digital.bios.business.core.utils.BeltCloudMathUtil;
import com.jwds.digital.bios.business.core.utils.BeltCloudTimeUtil;
import com.jwds.digital.bios.business.core.utils.BeltCloudUtil;
import com.jwds.digital.bios.business.rpc.feign.FlowBasicFeign;
import com.jwds.digital.bios.business.service.service.belt.*;
import com.jwds.tdc.framework.cache.service.CacheService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

/**
 * <p>BeltRouteJobCoreHandleServiceImpl 路线作业统计实现类</p>
 *
 * @author 林柏云
 * @Date：2024/11/27 10:55
 */
@Slf4j
@Service
public class BeltRouteJobCoreHandleServiceImpl implements IBeltRouteJobCoreHandleService {

  @Resource
  private CacheService cacheService;

  @Resource
  private IBeltPerformanceMinuteService beltPerformanceMinuteService;

  @Resource
  private IBeltRouteTaskDetailService beltRouteTaskDetailService;

  @Resource
  private IBeltRouteTaskMainService beltRouteTaskMainService;

  @Resource
  private IBeltRouteTaskBeltDetailService beltRouteTaskBeltDetailService;

  @Resource
  private IBeltRouteTargetHisService beltRouteTargetHisService;

  @Resource
  private IBeltDayTargetHisService beltDayTargetHisService;

  @Resource
  private IBeltRouteTaskBeltMainService beltRouteTaskBeltMainService;

  @Resource
  private IBeltAnomalyInfoService beltAnomalyInfoService;

  @Resource
  private FlowBasicFeign flowBasicFeign;

  @Autowired
  @Qualifier("routeJobTaskThreadPool")
  private ThreadPoolTaskExecutor taskExecutor;


  @PostConstruct
  public void test(){
    System.out.println("====================test====================");
  }

  @Override
  public void doStatisticsRouteJob() {
    // 获取缓存中所有正在运行的路线
    Set<String> keyList = cacheService.getKeys(BeltCloudConstant.BC_RUNNING_ROUTE_KEY + "*");
    for (String key : keyList) {
      if (StrUtil.isNotEmpty(cacheService.getString(key))) {
        BeltRouteBelongData belongData = JSONUtil.toBean(cacheService.getString(key), BeltRouteBelongData.class);
        doAndCheckStatisticsRouteJob(belongData);
      }
    }
  }

  /**
   * 统计路线作业统计任务
   * @param belongData
   */
  private void doAndCheckStatisticsRouteJob(BeltRouteBelongData belongData){
    LocalDateTime statisticsStartTime = null;
    BeltRouteTaskDetail lastRouteTaskDetail = beltRouteTaskDetailService.getOne(new LambdaQueryWrapper<BeltRouteTaskDetail>()
        .eq(BeltRouteTaskDetail::getTaskId, belongData.getTaskId())
        .orderByDesc(BeltRouteTaskDetail::getStartTime)
        .last("limit 1"));

    //作业已经结束，并且已经统计过，则跳过
    if(ObjectUtil.isNotNull(lastRouteTaskDetail) && ObjectUtil.isNotNull(belongData.getEndTime()) && lastRouteTaskDetail.getEndTime().isEqual(belongData.getEndTime())){
      return;
    }
    if(ObjectUtil.isNotNull(lastRouteTaskDetail)){
      statisticsStartTime = lastRouteTaskDetail.getEndTime();
    }else{
      statisticsStartTime = belongData.getStartTime();
    }
    LocalDateTime statisticsEndTime = BeltCloudTimeUtil.getNextStatisticsEndTime(statisticsStartTime, BeltCloudConstant.BC_ROUTE_JOB_STATISTICS_INTERVAL);
    LocalDateTime nowTime = LocalDateTime.now();
    //如果路线已经结束，则统计到结束时间
    if(ObjectUtil.isNotNull(belongData.getEndTime()) && statisticsEndTime.isAfter(belongData.getEndTime())){
      statisticsEndTime = belongData.getEndTime();
    }
    //时间未到，跳过
    if(statisticsEndTime.isAfter(nowTime)){
      return;
    }

    FlowBasicReqDTO reqDTO = new FlowBasicReqDTO();
    reqDTO.setFlowNo(belongData.getFlowNo());
    FlowBasicRespVO flowBasicRespVO = flowBasicFeign.all(reqDTO).getData().get(0);
    if(ObjectUtil.isNull(flowBasicRespVO)){
      log.error("获取路线信息失败，flowNo:{}", belongData.getFlowNo());
      return;
    }
    //查询时间段内，该作业-路线下所有的分钟级别数据
    List<BeltPerformanceMinute> minuteList = beltPerformanceMinuteService.list(
        new LambdaQueryWrapper<BeltPerformanceMinute>().eq(BeltPerformanceMinute::getTaskId, belongData.getTaskId())
            .eq(BeltPerformanceMinute::getFlowNo, belongData.getFlowNo())
            .ge(BeltPerformanceMinute::getStartTime, statisticsStartTime)
            .le(BeltPerformanceMinute::getEndTime, statisticsEndTime)
    );

    if(CollectionUtil.isEmpty(minuteList)){
      log.error("获取路线分钟数据为空，taskId:{}, flowNo:{}, statisticsStartTime:{}, statisticsEndTime:{}", belongData.getTaskId(), belongData.getFlowNo(), statisticsStartTime, statisticsEndTime);
      return;
    }
    /** 路线作业统计进行中，一个belongData代表一个路线作业 **/
    addRouteTaskDetailExecutor(minuteList, flowBasicRespVO, belongData ,statisticsStartTime, statisticsEndTime);
    /** 统计作业路线下的单条皮带  minuteList是一条路线、一个作业的分钟数据 **/
    addBeltTaskDetailExecutor(minuteList, statisticsStartTime, statisticsEndTime, belongData);
    /** 递归 **/
    doAndCheckStatisticsRouteJob(belongData);

  }

  /**
   * 更新天级别的历史指标数据
   */
  @Override
  public void updateBeltDayTargetHis(){
    LocalDateTime nowTime = LocalDateTime.now();
    LocalDateTime startTime = nowTime.minusWeeks(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
    LocalDateTime endTime = nowTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
    List<BeltRouteTaskMain> mainList = beltRouteTaskMainService.list(new QueryWrapper<BeltRouteTaskMain>().lambda()
        .ge(BeltRouteTaskMain::getStartTime, startTime)
        .le(BeltRouteTaskMain::getEndTime, endTime));
    //平均每天耗电量
    BigDecimal avgDayPowerConsumption = mainList.stream().map(BeltRouteTaskMain::getTotalPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(7), 2, RoundingMode.HALF_UP);
    //平均每天作业效率
    BigDecimal avgDayRunningEfficiency = mainList.stream().map(BeltRouteTaskMain::getWorkEfficiency).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(7), 2, RoundingMode.HALF_UP);
    //平均每天吨耗电量
    BigDecimal avgDayTonPowerConsumption = mainList.stream().map(BeltRouteTaskMain::getTonPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(7), 2, RoundingMode.HALF_UP);
    //平均每天空载运行时长
    BigDecimal avgDayEmptyLoadRunTime = mainList.stream().map(BeltRouteTaskMain::getUnLoadRunningTime).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(7), 2, RoundingMode.HALF_UP);
    //平均每天空载耗电量占比
    BigDecimal avgDayEmptyLoadRunEnergy = mainList.stream().map(BeltRouteTaskMain::getUnLoadPowerConsumptionRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(7), 2, RoundingMode.HALF_UP);

    //更新历史指标数据
    BeltDayTargetHis dayTargetHis = beltDayTargetHisService.getOne(new QueryWrapper<BeltDayTargetHis>().lambda()
        .eq(BeltDayTargetHis::getIsDeleted, 0)
        .orderByDesc(BeltDayTargetHis::getCreateTime)
        .last("LIMIT 1"));
    if(ObjectUtil.isNotNull(dayTargetHis)){
      dayTargetHis.setTotalPowerConsumption(avgDayPowerConsumption);
      dayTargetHis.setWorkEfficiency(avgDayRunningEfficiency);
      dayTargetHis.setTonPowerConsumption(avgDayTonPowerConsumption);
      dayTargetHis.setUnLoadRunningTime(avgDayEmptyLoadRunTime);
      dayTargetHis.setUnLoadPowerConsumptionRate(avgDayEmptyLoadRunEnergy);
      beltDayTargetHisService.updateById(dayTargetHis);
    }else {
      BeltDayTargetHis dayTargetHisNew = new BeltDayTargetHis();
      dayTargetHisNew.setTotalPowerConsumption(avgDayPowerConsumption);
      dayTargetHisNew.setWorkEfficiency(avgDayRunningEfficiency);
      dayTargetHisNew.setTonPowerConsumption(avgDayTonPowerConsumption);
      dayTargetHisNew.setUnLoadRunningTime(avgDayEmptyLoadRunTime);
      dayTargetHisNew.setUnLoadPowerConsumptionRate(avgDayEmptyLoadRunEnergy);
      beltDayTargetHisService.save(dayTargetHisNew);
    }
  }

  @Override
  public void doRouteAnomalyCheck() {
      beltAnomalyInfoService.searchForRouteExceptions();
  }

  @Override
  public void doBeltAnomalyCheck() {
    beltAnomalyInfoService.searchForBeltExceptions();
  }

  @Override
  public void doFiveDefenseCheck() {
    beltAnomalyInfoService.fiveDefenseCheck();
  }

  /**
   * 添加路线任务详情，belongData属于一个线路一个作业
   * @param belongData
   * @param finalStatisticsStartTime
   * @param finalStatisticsEndTime
   */
  private void addRouteTaskDetailExecutor(List<BeltPerformanceMinute> minuteList, FlowBasicRespVO flowBasicRespVO, BeltRouteBelongData belongData, LocalDateTime finalStatisticsStartTime, LocalDateTime finalStatisticsEndTime)  {
    //taskExecutor.execute(() -> {
      // 所有皮带负载、空载的分钟信息
      List<BeltPerformanceMinute> oneMinLoadList = minuteList.stream().filter(minuteData -> minuteData.getLoadStatus() == 1).collect(Collectors.toList());
      List<BeltPerformanceMinute> oneMinUnLoadList = minuteList.stream().filter(minuteData -> minuteData.getLoadStatus() == 0).collect(Collectors.toList());
      // 获取任意一条皮带的所有数据（这里选择第一条）
      List<BeltPerformanceMinute> oneBeltMinList = minuteList.stream().filter(m -> m.getBeltCode().equals(flowBasicRespVO.getStartDeviceCode()))
          .sorted(Comparator.comparing(BeltPerformanceMinute::getStartTime))
          .collect(Collectors.toList());
      if(CollectionUtil.isEmpty(oneBeltMinList)){
        log.error("获取第一条皮带分钟数据为空，taskId:{}, flowNo:{}, finalStatisticsStartTime:{}, finalStatisticsEndTime:{}", belongData.getTaskId(), belongData.getFlowNo(), finalStatisticsStartTime, finalStatisticsEndTime);
        return;
      }
      // 一条皮带负载、空载的分钟信息（这边认为一条路线下所有皮带的负载、空载时长是一致的）
      List<BeltPerformanceMinute> oneBeltMinLoadList = oneBeltMinList.stream().filter(minuteData -> minuteData.getLoadStatus() == 1).collect(Collectors.toList());
      List<BeltPerformanceMinute> oneBeltMinUnLoadList = oneBeltMinList.stream().filter(minuteData -> minuteData.getLoadStatus() == 0).collect(Collectors.toList());
      //累计运输量
      BigDecimal totalTransport = oneBeltMinList.stream().map(BeltPerformanceMinute::getTotalTransport).reduce(BigDecimal.ZERO, BigDecimal::add);
      //作业时长
      BigDecimal totalRunTime = BigDecimal.valueOf(oneBeltMinList.stream().mapToInt(BeltPerformanceMinute::getRuntime).sum()/60.0).setScale(2, RoundingMode.HALF_UP);
      //运输效率（t/h）
      BigDecimal transportEfficiency = totalTransport.divide(totalRunTime.divide(new BigDecimal(60), 2, BigDecimal.ROUND_HALF_UP), 2, BigDecimal.ROUND_HALF_UP);
      // 负载率、负载负载率、空负载率
      BigDecimal avgAllLoadRate = minuteList.stream().map(BeltPerformanceMinute::getAvgLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(minuteList.size()), 0, RoundingMode.HALF_UP);
      BigDecimal avgLoadRate = CollectionUtil.isEmpty(oneMinLoadList) ? BigDecimal.ZERO : oneMinLoadList.stream().map(BeltPerformanceMinute::getAvgLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(oneMinLoadList.size()), 0, RoundingMode.HALF_UP);
      BigDecimal avgUnLoadRate = CollectionUtil.isEmpty(oneMinUnLoadList) ? BigDecimal.ZERO : oneMinUnLoadList.stream().map(BeltPerformanceMinute::getAvgLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(oneMinUnLoadList.size()), 0, RoundingMode.HALF_UP);
      // 负载时长、空载时长、负载占比
      BigDecimal oneBeltLoadRunningTime = BigDecimal.valueOf(oneBeltMinLoadList.stream().mapToInt(BeltPerformanceMinute::getRuntime).sum()/60.0).setScale(2, RoundingMode.HALF_UP);
      BigDecimal oneBeltUnLoadRunningTime = BigDecimal.valueOf(oneBeltMinUnLoadList.stream().mapToInt(BeltPerformanceMinute::getRuntime).sum()/60.0).setScale(2, RoundingMode.HALF_UP);
      BigDecimal loadRatio = oneBeltLoadRunningTime.divide(oneBeltLoadRunningTime.add(oneBeltUnLoadRunningTime), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
      // 所有电耗、负载电耗、空载电耗、负载耗电量占比、空载耗电量占比
      BigDecimal totalPowerConsumption = minuteList.stream().map(BeltPerformanceMinute::getPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      BigDecimal loadPowerConsumption = oneMinLoadList.stream().map(BeltPerformanceMinute::getPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      BigDecimal unLoadPowerConsumption = oneMinUnLoadList.stream().map(BeltPerformanceMinute::getPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      BigDecimal loadPowerConsumptionRate = loadPowerConsumption.divide(totalPowerConsumption, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
      BigDecimal unLoadPowerConsumptionRatio = unLoadPowerConsumption.divide(totalPowerConsumption, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
      // 运行效率
      BigDecimal workEfficiency = minuteList.stream().map(BeltPerformanceMinute::getOperationEfficiency).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(minuteList.size()), 2, RoundingMode.HALF_UP);
      // 吨耗电量（t/kwh）
      BigDecimal tonPowerConsumption = totalTransport.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : totalPowerConsumption.divide(totalTransport, 2, RoundingMode.HALF_UP);
      // 负载均衡(算负载情况下的均衡)
      List<BigDecimal> avgLoadRateList = oneBeltMinLoadList.stream().map(BeltPerformanceMinute::getAvgLoadRate).collect(Collectors.toList());
      BigDecimal loadBalance = CollectionUtil.isEmpty(avgLoadRateList) ? BigDecimal.ZERO : BeltCloudMathUtil.calculateVariance(avgLoadRateList);
      // 料流均衡
      List<BigDecimal> totalTransportList = oneBeltMinList.stream().map(BeltPerformanceMinute::getTotalTransport).collect(Collectors.toList());
      BigDecimal trafficBalance = BeltCloudMathUtil.calculateVariance(totalTransportList);
      //平均阻力
      BigDecimal avgResistance = minuteList.stream().map(BeltPerformanceMinute::getAvgResistance).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(minuteList.size()), 2, RoundingMode.HALF_UP);
      //能耗效率评价
      String energyEfficiency = getEnergyEfficiencyByTarget(belongData.getFlowNo(), tonPowerConsumption, workEfficiency, transportEfficiency);

      BeltRouteTaskDetail detail = new BeltRouteTaskDetail();
      detail.setTaskId(belongData.getTaskId());
      detail.setFlowNo(belongData.getFlowNo());
      detail.setRouteCode(flowBasicRespVO.getFlowCode());
      detail.setStartTime(finalStatisticsStartTime);
      detail.setEndTime(finalStatisticsEndTime);
      detail.setRunningTime(totalRunTime);
      detail.setLoadRunningTime(oneBeltLoadRunningTime);
      detail.setUnLoadRunningTime(oneBeltUnLoadRunningTime);
      detail.setLoadRatio(loadRatio);
      detail.setTotalTransport(totalTransport);
      detail.setTransportEfficiency(transportEfficiency);
      detail.setAvgAllLoadRate(avgAllLoadRate);
      detail.setAvgLoadRate(avgLoadRate);
      detail.setAvgUnLoadRate(avgUnLoadRate);
      detail.setTotalPowerConsumption(totalPowerConsumption);
      detail.setLoadPowerConsumption(loadPowerConsumption);
      detail.setUnLoadPowerConsumption(unLoadPowerConsumption);
      detail.setLoadPowerConsumptionRate(loadPowerConsumptionRate);
      detail.setUnLoadPowerConsumptionRate(unLoadPowerConsumptionRatio);
      detail.setWorkEfficiency(workEfficiency);
      detail.setTonPowerConsumption(tonPowerConsumption);
      detail.setLoadBalance(loadBalance);
      detail.setTrafficBalance(trafficBalance);
      detail.setAvgResistance(avgResistance);
      detail.setEnergyEfficiency(energyEfficiency);
      detail.setSpikePowerConsumption(BigDecimal.ZERO);
      detail.setPeakPowerConsumption(BigDecimal.ZERO);
      detail.setFlatPowerConsumption(BigDecimal.ZERO);
      detail.setValleyPowerConsumption(BigDecimal.ZERO);
      //电耗类型（5分钟内的电耗类型一致）
      if(minuteList.get(0).getPowerType() == BeltCloudUtil.SPIKE_POWER){
        detail.setSpikePowerConsumption(totalPowerConsumption);
      }else if(minuteList.get(0).getPowerType() == BeltCloudUtil.PEAK_POWER){
        detail.setPeakPowerConsumption(totalPowerConsumption);
      }else if(minuteList.get(0).getPowerType() == BeltCloudUtil.FLAT_POWER){
        detail.setFlatPowerConsumption(totalPowerConsumption);
      }else if(minuteList.get(0).getPowerType() == BeltCloudUtil.VALLEY_POWER){
        detail.setValleyPowerConsumption(totalPowerConsumption);
      }
      beltRouteTaskDetailService.save(detail);
      /** 合并到main **/
      combineDetailToRouteTaskMain(detail, belongData);
    //});
  }

  /**
   * 合并 beltRouteTaskDetail 到 routeTask (一个作业实绩对应多个小时间段作业实绩，方便快速计算)
   * @param detail 即将要合并的路线任务详情
   */
  private void combineDetailToRouteTaskMain(BeltRouteTaskDetail detail, BeltRouteBelongData belongData){

    // 第一条数据标志
    boolean firstData = false;
    BeltRouteTaskMain routeTaskMain = beltRouteTaskMainService.getOne(new LambdaQueryWrapper<BeltRouteTaskMain>()
        .eq(BeltRouteTaskMain::getFlowNo, detail.getFlowNo())
        .eq(BeltRouteTaskMain::getTaskId, detail.getTaskId())
        .last("limit 1"));
    if(ObjectUtil.isNull(routeTaskMain)){
      firstData = true;
      routeTaskMain = new BeltRouteTaskMain();
      routeTaskMain.setRouteCode(detail.getRouteCode());
      routeTaskMain.setTaskId(detail.getTaskId());
      routeTaskMain.setFlowNo(detail.getFlowNo());
      routeTaskMain.setStartTime(belongData.getStartTime());
      routeTaskMain.setRunningTime(detail.getRunningTime());
      routeTaskMain.setLoadRunningTime(detail.getLoadRunningTime());
      routeTaskMain.setUnLoadRunningTime(detail.getUnLoadRunningTime());
      routeTaskMain.setTotalTransport(detail.getTotalTransport());
      routeTaskMain.setTransportEfficiency(detail.getTransportEfficiency());
      routeTaskMain.setAvgAllLoadRate(detail.getAvgAllLoadRate());
      routeTaskMain.setAvgLoadRate(detail.getAvgLoadRate());
      routeTaskMain.setAvgUnLoadRate(detail.getAvgUnLoadRate());
      routeTaskMain.setTotalPowerConsumption(detail.getTotalPowerConsumption());
      routeTaskMain.setLoadPowerConsumption(detail.getLoadPowerConsumption());
      routeTaskMain.setUnLoadPowerConsumption(detail.getUnLoadPowerConsumption());
      routeTaskMain.setWorkEfficiency(detail.getWorkEfficiency());
      routeTaskMain.setTonPowerConsumption(detail.getTonPowerConsumption());
      routeTaskMain.setLoadBalance(detail.getLoadBalance());
      routeTaskMain.setTrafficBalance(detail.getTrafficBalance());
      routeTaskMain.setAvgResistance(detail.getAvgResistance());
      routeTaskMain.setSpikePowerConsumption(detail.getSpikePowerConsumption());
      routeTaskMain.setPeakPowerConsumption(detail.getPeakPowerConsumption());
      routeTaskMain.setValleyPowerConsumption(detail.getValleyPowerConsumption());
      routeTaskMain.setFlatPowerConsumption(detail.getFlatPowerConsumption());
    }else {
      routeTaskMain.setRunningTime(routeTaskMain.getRunningTime().add(detail.getRunningTime()));
      routeTaskMain.setLoadRunningTime(routeTaskMain.getLoadRunningTime().add(detail.getLoadRunningTime()));
      routeTaskMain.setUnLoadRunningTime(routeTaskMain.getUnLoadRunningTime().add(detail.getUnLoadRunningTime()));
      routeTaskMain.setTotalTransport(routeTaskMain.getTotalTransport().add(detail.getTotalTransport()));
      routeTaskMain.setTotalPowerConsumption(routeTaskMain.getTotalPowerConsumption().add(detail.getTotalPowerConsumption()));
      routeTaskMain.setLoadPowerConsumption(routeTaskMain.getLoadPowerConsumption().add(detail.getLoadPowerConsumption()));
      routeTaskMain.setUnLoadPowerConsumption(routeTaskMain.getUnLoadPowerConsumption().add(detail.getUnLoadPowerConsumption()));
      routeTaskMain.setSpikePowerConsumption(routeTaskMain.getSpikePowerConsumption().add(detail.getSpikePowerConsumption()));
      routeTaskMain.setPeakPowerConsumption(routeTaskMain.getPeakPowerConsumption().add(detail.getPeakPowerConsumption()));
      routeTaskMain.setValleyPowerConsumption(routeTaskMain.getValleyPowerConsumption().add(detail.getValleyPowerConsumption()));
      routeTaskMain.setFlatPowerConsumption(routeTaskMain.getFlatPowerConsumption().add(detail.getFlatPowerConsumption()));
    }

    // 如果有结束时间，则设置结束时间
    if(ObjectUtil.isNotNull(belongData.getEndTime())) {
      routeTaskMain.setEndTime(belongData.getEndTime());
    }
    // 第一次料流信号时间
    if(ObjectUtil.isNull(routeTaskMain.getFirstMaterialFlowTime())) {
      if(detail.getLoadRunningTime().compareTo(BigDecimal.ZERO) > 0) {
        long differSecond = detail.getRunningTime().multiply(BigDecimal.valueOf(60)).subtract(routeTaskMain.getLoadRunningTime().multiply(BigDecimal.valueOf(60))).setScale(0, RoundingMode.UP).longValue();
        LocalDateTime firstLoadTime = detail.getStartTime().plusSeconds(differSecond);
        routeTaskMain.setFirstMaterialFlowTime(firstLoadTime);
        routeTaskMain.setUnLoadPowerConsumption(routeTaskMain.getTotalPowerConsumption().subtract(detail.getTotalPowerConsumption()));
      }
    }
    //最后一次料流信号时间
    if(ObjectUtil.isNotNull(belongData.getEndTime()) && ObjectUtil.isNotNull(routeTaskMain.getFirstMaterialFlowTime())) {
      BeltRouteTaskDetail lastLoadData = null;
      if(detail.getLoadRunningTime().compareTo(BigDecimal.ZERO) > 0 && detail.getUnLoadRunningTime().compareTo(BigDecimal.ZERO) > 0)  {
        lastLoadData = detail;
      }else{
        //数据库去查询
        lastLoadData = beltRouteTaskDetailService.getOne(new LambdaQueryWrapper<BeltRouteTaskDetail>()
            .gt(BeltRouteTaskDetail::getLoadRunningTime, BigDecimal.ZERO)
            .eq(BeltRouteTaskDetail::getTaskId, detail.getTaskId())
            .orderByDesc(BeltRouteTaskDetail::getStartTime)
            .last("limit 1"));
      }
      long differSecond = lastLoadData.getRunningTime().multiply(BigDecimal.valueOf(60)).subtract(routeTaskMain.getUnLoadRunningTime().multiply(BigDecimal.valueOf(60))).setScale(0, RoundingMode.UP).longValue();
      LocalDateTime lastLoadTime = lastLoadData.getStartTime().plusSeconds(differSecond);
      routeTaskMain.setLastMaterialFlowTime(lastLoadTime);
    }

    //分摊负载率\负载负载率\空载负载率\运行效率
    if(!firstData){
      if(routeTaskMain.getRunningTime().compareTo(BigDecimal.ZERO) > 0) {
        BigDecimal resultAvgAllLoadRate = routeTaskMain.getAvgAllLoadRate().multiply(BigDecimal.ONE.subtract(detail.getRunningTime().divide(routeTaskMain.getRunningTime(), 4, RoundingMode.HALF_UP)))
            .add(detail.getAvgAllLoadRate().multiply(detail.getRunningTime().divide(routeTaskMain.getRunningTime(), 4, RoundingMode.HALF_UP)));
        routeTaskMain.setAvgLoadRate(resultAvgAllLoadRate);
      }
      if(routeTaskMain.getUnLoadRunningTime().compareTo(BigDecimal.ZERO) > 0) {
        BigDecimal resultAvgUnLoadRate = routeTaskMain.getAvgUnLoadRate().multiply(BigDecimal.ONE.subtract(detail.getUnLoadRunningTime().divide(routeTaskMain.getUnLoadRunningTime(), 4, RoundingMode.HALF_UP)))
            .add(detail.getAvgUnLoadRate().multiply(detail.getUnLoadRunningTime().divide(routeTaskMain.getUnLoadRunningTime(), 4, RoundingMode.HALF_UP)));
        routeTaskMain.setAvgUnLoadRate(resultAvgUnLoadRate);
      }
      if(routeTaskMain.getLoadRunningTime().compareTo(BigDecimal.ZERO) > 0) {
        BigDecimal resultAvgLoadRate = routeTaskMain.getAvgLoadRate().multiply(BigDecimal.ONE.subtract(detail.getLoadRunningTime().divide(routeTaskMain.getLoadRunningTime(), 4, RoundingMode.HALF_UP)))
            .add(detail.getAvgLoadRate().multiply(detail.getLoadRunningTime().divide(routeTaskMain.getLoadRunningTime(), 4, RoundingMode.HALF_UP)));
        routeTaskMain.setAvgLoadRate(resultAvgLoadRate);
      }
      if(routeTaskMain.getRunningTime().compareTo(BigDecimal.ZERO) > 0) {
        BigDecimal resultWorkEfficiency = routeTaskMain.getWorkEfficiency().multiply(BigDecimal.ONE.subtract(detail.getRunningTime().divide(routeTaskMain.getRunningTime(), 4, RoundingMode.HALF_UP)))
            .add(detail.getWorkEfficiency().multiply(detail.getRunningTime().divide(routeTaskMain.getRunningTime(), 4, RoundingMode.HALF_UP)));
        routeTaskMain.setAvgLoadRate(resultWorkEfficiency);
      }
    }
    //负载比率
    routeTaskMain.setLoadRatio(routeTaskMain.getLoadRunningTime().divide(routeTaskMain.getRunningTime(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
    //运输效率
    routeTaskMain.setTransportEfficiency(routeTaskMain.getTotalTransport().divide(routeTaskMain.getRunningTime(), 4, RoundingMode.HALF_UP));
    //负载耗电量占比
    routeTaskMain.setLoadPowerConsumptionRate(routeTaskMain.getLoadPowerConsumption().divide(routeTaskMain.getTotalPowerConsumption(), 4 , RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
    //空载耗电量占比
    routeTaskMain.setUnLoadPowerConsumptionRate(routeTaskMain.getUnLoadPowerConsumption().divide(routeTaskMain.getTotalPowerConsumption(), 4 , RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
    //吨料耗电量
    if(ObjectUtil.isNotNull(routeTaskMain.getTotalTransport()) && routeTaskMain.getTotalTransport().compareTo(BigDecimal.ZERO) > 0) {
        routeTaskMain.setTonPowerConsumption(routeTaskMain.getTotalPowerConsumption().divide(routeTaskMain.getTotalTransport(), 2, RoundingMode.UP));
    }
    //启动空载运行时长
    if(ObjectUtil.isNull(routeTaskMain.getStartupNoLoadDuration()) && ObjectUtil.isNotNull(routeTaskMain.getFirstMaterialFlowTime())){
      long sec = ChronoUnit.SECONDS.between(routeTaskMain.getFirstMaterialFlowTime(), routeTaskMain.getStartTime());
      routeTaskMain.setStartupNoLoadDuration(BigDecimal.valueOf(sec/60).setScale(2, RoundingMode.UP));
    }
    //停止空载运行时长
    if(ObjectUtil.isNull(routeTaskMain.getShutdownNoLoadDuration()) && ObjectUtil.isNotNull(routeTaskMain.getLastMaterialFlowTime()) && ObjectUtil.isNotNull(routeTaskMain.getEndTime())){
      long sec = ChronoUnit.SECONDS.between(routeTaskMain.getEndTime(), routeTaskMain.getLastMaterialFlowTime());
      routeTaskMain.setShutdownNoLoadDuration(BigDecimal.valueOf(sec/60).setScale(2, RoundingMode.UP));
    }
    //运行中空载运行时长
    BigDecimal runningNoLoadDuration = routeTaskMain.getUnLoadRunningTime();
    if(ObjectUtil.isNotNull(routeTaskMain.getStartupNoLoadDuration())){
      runningNoLoadDuration = runningNoLoadDuration.subtract(routeTaskMain.getStartupNoLoadDuration());
    }
    if(ObjectUtil.isNotNull(routeTaskMain.getShutdownNoLoadDuration())){
      runningNoLoadDuration = runningNoLoadDuration.subtract(routeTaskMain.getShutdownNoLoadDuration());
    }
    routeTaskMain.setRunningNoLoadDuration(runningNoLoadDuration);
    // 运行负载运行时长
    routeTaskMain.setRunningLoadDuration(routeTaskMain.getLoadRunningTime());
    //启动空载运行电耗
    if(ObjectUtil.isNull(routeTaskMain.getStartupNoLoadPower()) && ObjectUtil.isNotNull(routeTaskMain.getFirstMaterialFlowTime())){
      List<BeltRouteTaskDetail> startupNoLoadList = beltRouteTaskDetailService.list(new LambdaQueryWrapper<BeltRouteTaskDetail>()
          .eq(BeltRouteTaskDetail::getTaskId, detail.getTaskId())
          .between(BeltRouteTaskDetail::getStartTime, routeTaskMain.getStartTime(), routeTaskMain.getFirstMaterialFlowTime()));
      BigDecimal startupNoLoadPower = startupNoLoadList.stream().map(BeltRouteTaskDetail::getUnLoadPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      routeTaskMain.setStartupNoLoadPower(startupNoLoadPower);
    }
    //停止空载运行电耗
    if(ObjectUtil.isNull(routeTaskMain.getShutdownNoLoadPower()) && ObjectUtil.isNotNull(routeTaskMain.getLastMaterialFlowTime())){
      List<BeltRouteTaskDetail> shutdownNoLoadList = beltRouteTaskDetailService.list(new LambdaQueryWrapper<BeltRouteTaskDetail>()
              .eq(BeltRouteTaskDetail::getTaskId, detail.getTaskId())
              .between(BeltRouteTaskDetail::getEndTime, routeTaskMain.getLastMaterialFlowTime(), routeTaskMain.getEndTime()));
      BigDecimal shutdownNoLoadPower = shutdownNoLoadList.stream().map(BeltRouteTaskDetail::getUnLoadPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      routeTaskMain.setShutdownNoLoadPower(shutdownNoLoadPower);
    }
    //运行空载运行电耗\运行中负载运行电耗
    if(ObjectUtil.isNotNull(routeTaskMain.getFirstMaterialFlowTime())){
      LambdaQueryWrapper<BeltRouteTaskDetail> wrapper = new LambdaQueryWrapper<BeltRouteTaskDetail>().eq(BeltRouteTaskDetail::getTaskId, detail.getTaskId());
      if(ObjectUtil.isNotNull(routeTaskMain.getLastMaterialFlowTime())){
        wrapper.between(BeltRouteTaskDetail::getStartTime, routeTaskMain.getFirstMaterialFlowTime(), routeTaskMain.getLastMaterialFlowTime());
      } else {
        wrapper.ge(BeltRouteTaskDetail::getStartTime, routeTaskMain.getFirstMaterialFlowTime());
      }
      List<BeltRouteTaskDetail> runningList = beltRouteTaskDetailService.list(wrapper);
      BigDecimal runningNoLoadPower = runningList.stream().map(BeltRouteTaskDetail::getUnLoadPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      routeTaskMain.setRunningNoLoadPower(runningNoLoadPower);
      BigDecimal runningLoadPower = runningList.stream().map(BeltRouteTaskDetail::getLoadPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      routeTaskMain.setRunningLoadPower(runningLoadPower);
    }

    List<BeltRouteTaskDetail> detailList = beltRouteTaskDetailService.list(new LambdaQueryWrapper<BeltRouteTaskDetail>()
        .eq(BeltRouteTaskDetail::getTaskId, detail.getTaskId()));
    //负载均衡
    List<BigDecimal> avgLoadRateList = detailList.stream().map(BeltRouteTaskDetail::getAvgLoadRate).collect(Collectors.toList());
    BigDecimal loadBalance = BeltCloudMathUtil.calculateVariance(avgLoadRateList);
    //料流均衡
    List<BigDecimal> momentWeightList = detailList.stream().map(BeltRouteTaskDetail::getTotalTransport).collect(Collectors.toList());
    BigDecimal trafficBalance = BeltCloudMathUtil.calculateVariance(momentWeightList);
    routeTaskMain.setLoadBalance(loadBalance);
    routeTaskMain.setTrafficBalance(trafficBalance);

    //能效评价
    String energyEfficiency = getEnergyEfficiencyByTarget(routeTaskMain.getFlowNo(), routeTaskMain.getTonPowerConsumption(), routeTaskMain.getWorkEfficiency(), routeTaskMain.getTransportEfficiency());
    routeTaskMain.setEnergyEfficiency(energyEfficiency);

    if(firstData){
      beltRouteTaskMainService.save(routeTaskMain);
    }else {
      beltRouteTaskMainService.updateById(routeTaskMain);
    }
    if(ObjectUtil.isNotNull(routeTaskMain.getEndTime()) && detail.getEndTime().isEqual(routeTaskMain.getEndTime())){
      //代表作业完成
      updateBeltRouteTargetHis(routeTaskMain.getFlowNo());
    }
  }

  /**
   * 单条皮带的统计(前提是分钟数据已经统计完成)
   * 注意：minuteList是一个路线作业的分钟信息
   * @param minuteList
   * @param finalStatisticsStartTime
   * @param finalStatisticsEndTime
   */
  private void addBeltTaskDetailExecutor(List<BeltPerformanceMinute> minuteList, LocalDateTime finalStatisticsStartTime, LocalDateTime finalStatisticsEndTime, BeltRouteBelongData belongData){
    //按皮带code分组
    Map<String,List<BeltPerformanceMinute>> beltMinuteListMap = minuteList.stream().collect(Collectors.groupingBy(BeltPerformanceMinute::getBeltCode));
    List<BeltRouteTaskBeltDetail> beltDetailList = new ArrayList<>();
    for (Map.Entry<String, List<BeltPerformanceMinute>> entry : beltMinuteListMap.entrySet()) {
      //单条皮带的分钟信息
      List<BeltPerformanceMinute> beltMinuteList = entry.getValue();
      beltMinuteList = beltMinuteList.stream().sorted(Comparator.comparing(BeltPerformanceMinute::getStartTime)).collect(Collectors.toList());
      // 所有皮带负载、空载的分钟信息
      List<BeltPerformanceMinute> beltLoadMinuteList = beltMinuteList.stream().filter(minuteData -> minuteData.getLoadStatus() == 1).collect(Collectors.toList());
      List<BeltPerformanceMinute> beltUnLoadMinuteList = beltMinuteList.stream().filter(minuteData -> minuteData.getLoadStatus() == 0).collect(Collectors.toList());
      BeltRouteTaskBeltDetail beltDetail = new BeltRouteTaskBeltDetail();
      beltDetail.setStartTime(finalStatisticsStartTime);
      beltDetail.setEndTime(finalStatisticsEndTime);
      beltDetail.setTaskId(beltMinuteList.get(0).getTaskId());
      beltDetail.setBeltCode(beltMinuteList.get(0).getBeltCode());
      beltDetail.setTaskType(null);
      beltDetail.setFlowNo(beltMinuteList.get(0).getFlowNo());
      //运行时间|负载时间|空载时间
      int runTimeSecondSum = beltMinuteList.stream().map(BeltPerformanceMinute::getRuntime).reduce(0, Integer::sum);
      beltDetail.setRunningTime(BigDecimal.valueOf(runTimeSecondSum/60.0).setScale(2, RoundingMode.HALF_UP));
      int loadTimeSecondSum = beltLoadMinuteList.stream().map(BeltPerformanceMinute::getRuntime).reduce(0, Integer::sum);
      beltDetail.setLoadRunningTime(BigDecimal.valueOf(loadTimeSecondSum/60.0).setScale(2, RoundingMode.HALF_UP));
      int unLoadTimeSecondSum = beltUnLoadMinuteList.stream().map(BeltPerformanceMinute::getRuntime).reduce(0, Integer::sum);
      beltDetail.setUnLoadRunningTime(BigDecimal.valueOf(unLoadTimeSecondSum/60.0).setScale(2, RoundingMode.HALF_UP));
      //累计运输量
      BigDecimal totalTransport = beltMinuteList.stream().map(BeltPerformanceMinute::getTotalTransport).reduce(BigDecimal.ZERO, BigDecimal::add);
      beltDetail.setTotalTransport(totalTransport);
      //运输效率
      BigDecimal transportEfficiency = totalTransport.divide(beltDetail.getRunningTime(), 2, RoundingMode.HALF_UP);
      beltDetail.setTransportEfficiency(transportEfficiency);
      //平均负载率|平均空载率|平均总负载率
      BigDecimal avgAllLoadRate = beltMinuteList.stream().map(BeltPerformanceMinute::getAvgLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(beltMinuteList.size()), 2, RoundingMode.HALF_UP);
      beltDetail.setAvgAllLoadRate(avgAllLoadRate);
      BigDecimal avgLoadRate = CollectionUtil.isEmpty(beltLoadMinuteList) ? BigDecimal.ZERO : beltLoadMinuteList.stream().map(BeltPerformanceMinute::getAvgLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(beltLoadMinuteList.size()), 2, RoundingMode.HALF_UP);
      beltDetail.setAvgLoadRate(avgLoadRate);
      BigDecimal avgUnLoadRate = CollectionUtil.isEmpty(beltUnLoadMinuteList) ? BigDecimal.ZERO : beltUnLoadMinuteList.stream().map(BeltPerformanceMinute::getAvgLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(beltUnLoadMinuteList.size()), 2, RoundingMode.HALF_UP);
      beltDetail.setAvgUnLoadRate(avgUnLoadRate);
      //总电耗|负载电耗|空载电耗
      BigDecimal totalPowerConsumption = beltMinuteList.stream().map(BeltPerformanceMinute::getPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      beltDetail.setTotalPowerConsumption(totalPowerConsumption);
      BigDecimal loadPowerConsumption = CollectionUtil.isEmpty(beltLoadMinuteList) ? BigDecimal.ZERO : beltLoadMinuteList.stream().map(BeltPerformanceMinute::getPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      beltDetail.setLoadPowerConsumption(loadPowerConsumption);
      BigDecimal unLoadPowerConsumption = CollectionUtil.isEmpty(beltUnLoadMinuteList) ? BigDecimal.ZERO : beltUnLoadMinuteList.stream().map(BeltPerformanceMinute::getPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add);
      beltDetail.setUnLoadPowerConsumption(unLoadPowerConsumption);
      //负载耗电量占比|空载耗电量占比
      BigDecimal loadPowerConsumptionRate = loadPowerConsumption.divide(totalPowerConsumption, 2, RoundingMode.HALF_UP);
      beltDetail.setLoadPowerConsumptionRate(loadPowerConsumptionRate);
      BigDecimal unLoadPowerConsumptionRate = unLoadPowerConsumption.divide(totalPowerConsumption, 2, RoundingMode.HALF_UP);
      beltDetail.setUnLoadPowerConsumptionRate(unLoadPowerConsumptionRate);
      //耗电类型
      beltDetail.setPowerType(beltMinuteList.get(0).getPowerType());
      //运行效率
      BigDecimal runningEfficiency = beltMinuteList.stream().map(BeltPerformanceMinute::getOperationEfficiency).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(beltMinuteList.size()), 2, RoundingMode.HALF_UP);
      beltDetail.setOperationEfficiency(runningEfficiency);
      //吨料耗电量
      BigDecimal tonPowerConsumption = totalTransport.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : totalPowerConsumption.divide(totalTransport, 2, RoundingMode.HALF_UP);
      beltDetail.setTonPowerConsumption(tonPowerConsumption);
      //平均阻力
      BigDecimal avgResistance = beltMinuteList.stream().map(BeltPerformanceMinute::getAvgResistance).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(beltMinuteList.size()), 2, RoundingMode.HALF_UP);
      beltDetail.setAvgResistance(avgResistance);
      beltRouteTaskBeltDetailService.save(beltDetail);
      beltDetailList.add(beltDetail);
    }
    combineBeltMain(beltDetailList,finalStatisticsStartTime,finalStatisticsEndTime, belongData);
  }

  /**
   * 整合到路线作业皮带主表
   * @param beltDetailList
   * @param finalStatisticsStartTime
   * @param finalStatisticsEndTime
   */
  private void combineBeltMain(List<BeltRouteTaskBeltDetail> beltDetailList, LocalDateTime finalStatisticsStartTime, LocalDateTime finalStatisticsEndTime, BeltRouteBelongData belongData){

    for (BeltRouteTaskBeltDetail beltDetail : beltDetailList) {
      BeltRouteTaskBeltMain beltRouteTaskBeltMain = beltRouteTaskBeltMainService.getOne(new QueryWrapper<BeltRouteTaskBeltMain>().lambda()
          .eq(BeltRouteTaskBeltMain::getBeltCode, beltDetail.getBeltCode())
          .eq(BeltRouteTaskBeltMain::getTaskId, beltDetail.getTaskId()).last("LIMIT 1"));
      if(ObjectUtil.isNull(beltRouteTaskBeltMain)){
        beltRouteTaskBeltMain = new BeltRouteTaskBeltMain();
        beltRouteTaskBeltMain.setStartTime(finalStatisticsStartTime);
        beltRouteTaskBeltMain.setBeltCode(beltDetail.getBeltCode());
        beltRouteTaskBeltMain.setRouteCode(beltDetail.getRouteCode());
        beltRouteTaskBeltMain.setTaskId(beltDetail.getTaskId());
        beltRouteTaskBeltMain.setTaskType(beltDetail.getTaskType());
        beltRouteTaskBeltMain.setFlowNo(beltDetail.getFlowNo());
        beltRouteTaskBeltMain.setWorkEfficiency(beltDetail.getTransportEfficiency());
        beltRouteTaskBeltMain.setTotalTransport(beltDetail.getTotalTransport());
        beltRouteTaskBeltMain.setOperationEfficiency(beltDetail.getOperationEfficiency());
        beltRouteTaskBeltMain.setRunningTime(beltDetail.getRunningTime());
        beltRouteTaskBeltMain.setNoLoadRuntime(beltDetail.getUnLoadRunningTime());
        beltRouteTaskBeltMain.setLoadRuntime(beltDetail.getLoadRunningTime());
        beltRouteTaskBeltMain.setAvgAllLoadRate(beltDetail.getAvgAllLoadRate());
        beltRouteTaskBeltMain.setTotalPowerConsumption(beltDetail.getTotalPowerConsumption());
        beltRouteTaskBeltMain.setLoadPowerConsumption(beltDetail.getLoadPowerConsumption());
        beltRouteTaskBeltMain.setNoLoadPowerConsumption(beltDetail.getUnLoadPowerConsumption());
        beltRouteTaskBeltMain.setTonPowerConsumption(beltDetail.getTonPowerConsumption());
        beltRouteTaskBeltMainService.save(beltRouteTaskBeltMain);
      }else {
        if(ObjectUtil.isNotNull(belongData.getEndTime()) && finalStatisticsEndTime.isEqual(belongData.getEndTime())){
          beltRouteTaskBeltMain.setEndTime(finalStatisticsEndTime);
        }
        beltRouteTaskBeltMain.setRunningTime(beltRouteTaskBeltMain.getRunningTime().add(beltDetail.getRunningTime()));
        beltRouteTaskBeltMain.setTotalTransport(beltRouteTaskBeltMain.getTotalTransport().add(beltDetail.getTotalTransport()));
        beltRouteTaskBeltMain.setNoLoadRuntime(beltRouteTaskBeltMain.getNoLoadRuntime().add(beltDetail.getUnLoadRunningTime()));
        beltRouteTaskBeltMain.setLoadRuntime(beltRouteTaskBeltMain.getLoadRuntime().add(beltDetail.getLoadRunningTime()));
        beltRouteTaskBeltMain.setTotalPowerConsumption(beltRouteTaskBeltMain.getTotalPowerConsumption().add(beltDetail.getTotalPowerConsumption()));
        beltRouteTaskBeltMain.setLoadPowerConsumption(beltRouteTaskBeltMain.getLoadPowerConsumption().add(beltDetail.getLoadPowerConsumption()));
        beltRouteTaskBeltMain.setNoLoadPowerConsumption(beltRouteTaskBeltMain.getNoLoadPowerConsumption().add(beltDetail.getUnLoadPowerConsumption()));
        beltRouteTaskBeltMain.setWorkEfficiency(beltRouteTaskBeltMain.getTotalTransport().divide(beltRouteTaskBeltMain.getRunningTime().divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP), 2, RoundingMode.HALF_UP));
        beltRouteTaskBeltMain.setTonPowerConsumption(beltRouteTaskBeltMain.getTotalPowerConsumption().divide(beltRouteTaskBeltMain.getTotalTransport(), 2, RoundingMode.HALF_UP));
        //占比份量
        BigDecimal portion = beltDetail.getRunningTime().divide(beltRouteTaskBeltMain.getRunningTime(), 5, RoundingMode.HALF_UP);
        beltRouteTaskBeltMain.setOperationEfficiency(beltRouteTaskBeltMain.getOperationEfficiency().multiply(BigDecimal.ONE.subtract(portion)).add(beltDetail.getOperationEfficiency().multiply(portion)));
        beltRouteTaskBeltMain.setAvgAllLoadRate(beltRouteTaskBeltMain.getAvgAllLoadRate().multiply(BigDecimal.ONE.subtract(portion)).add(beltDetail.getAvgAllLoadRate().multiply(portion)));
        beltRouteTaskBeltMainService.updateById(beltRouteTaskBeltMain);
      }
    }
  }

  /**
   * 更新历史指标数据，触发条件为流程下的作业完成后
   * @Param flowNo 流程编号
   */
  private void updateBeltRouteTargetHis(Short flowNo){
    LocalDateTime startTime = LocalDateTime.now().minusWeeks(2);
    List<BeltRouteTaskMain> mainList = beltRouteTaskMainService.list(new QueryWrapper<BeltRouteTaskMain>().lambda()
        .eq(BeltRouteTaskMain::getFlowNo, flowNo)
        .ge(BeltRouteTaskMain::getStartTime, startTime)
        .isNotNull(BeltRouteTaskMain::getEndTime)
        .orderByDesc(BeltRouteTaskMain::getStartTime)
        .last("limit 100")
    );
    //平均吨耗电量|优秀吨耗电量|及格吨耗电量
    BigDecimal avgTonPowerConsumption = mainList.stream().map(BeltRouteTaskMain::getTonPowerConsumption).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(mainList.size()), 2, RoundingMode.HALF_UP);
    BigDecimal excellentTonPowerConsumption = avgTonPowerConsumption.multiply(new BigDecimal("1.2")).setScale(2, RoundingMode.HALF_UP);
    BigDecimal passTonPowerConsumption = avgTonPowerConsumption.multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.HALF_UP);
    //平均运行效率|优秀运行效率|及格运行效率
    BigDecimal avgRunningEfficiency = mainList.stream().map(BeltRouteTaskMain::getWorkEfficiency).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(mainList.size()), 2, RoundingMode.HALF_UP);
    BigDecimal excellentRunningEfficiency = avgRunningEfficiency.multiply(new BigDecimal("1.2")).setScale(2, RoundingMode.HALF_UP);
    BigDecimal passRunningEfficiency = avgRunningEfficiency.multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.HALF_UP);
    //平均运输效率|优秀运输效率|及格运输效率
    BigDecimal avgTransportEfficiency = mainList.stream().map(BeltRouteTaskMain::getTransportEfficiency).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(mainList.size()), 2, RoundingMode.HALF_UP);
    BigDecimal excellentTransportEfficiency = avgTransportEfficiency.multiply(new BigDecimal("1.2")).setScale(2, RoundingMode.HALF_UP);
    BigDecimal passTransportEfficiency = avgTransportEfficiency.multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.HALF_UP);
    //平均负载率|优秀负载率|及格负载率
    BigDecimal avgLoadRate = mainList.stream().map(BeltRouteTaskMain::getAvgAllLoadRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(mainList.size()), 2, RoundingMode.HALF_UP);
    BigDecimal excellentLoadRate = avgLoadRate.multiply(new BigDecimal("1.2")).setScale(2, RoundingMode.HALF_UP);
    BigDecimal passLoadRate = avgLoadRate.multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.HALF_UP);
    //平均阻力|优秀阻力|及格阻力
    BigDecimal avgResistance = mainList.stream().map(BeltRouteTaskMain::getAvgResistance).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(mainList.size()), 2, RoundingMode.HALF_UP);
    BigDecimal excellentResistance = avgResistance.multiply(new BigDecimal("1.2")).setScale(2, RoundingMode.HALF_UP);
    BigDecimal passResistance = avgResistance.multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.HALF_UP);
    //空载运行时长
    BigDecimal emptyLoadRunTime = mainList.stream().map(BeltRouteTaskMain::getUnLoadRunningTime).reduce(BigDecimal.ZERO, BigDecimal::add);
    //空载运行能耗占比
    BigDecimal emptyLoadRunEnergy = mainList.stream().map(BeltRouteTaskMain::getUnLoadPowerConsumptionRate).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(mainList.size()), 2, RoundingMode.HALF_UP);
    //运行空载时长
    BigDecimal runningNoLoadDuration= mainList.stream().map(BeltRouteTaskMain::getRunningNoLoadDuration).reduce(BigDecimal.ZERO, BigDecimal::add);
    //运行时长
    BigDecimal runningTime = mainList.stream().map(BeltRouteTaskMain::getRunningTime).reduce(BigDecimal.ZERO, BigDecimal::add);
    //运行空载占比
    BigDecimal runningNoLoadRate = runningNoLoadDuration.divide(runningTime, 2, RoundingMode.HALF_UP);

    //更新历史指标数据
    BeltRouteTargetHis targetHis = beltRouteTargetHisService.getOne(new QueryWrapper<BeltRouteTargetHis>().lambda().eq(BeltRouteTargetHis::getFlowNo, flowNo).last("LIMIT 1"));
    if(ObjectUtil.isNotNull(targetHis)){
      targetHis.setTonPowerConsumption(avgTonPowerConsumption);
      targetHis.setTonPowerConsumptionExcellent(excellentTonPowerConsumption);
      targetHis.setTonPowerConsumptionWrong(passTonPowerConsumption);
      targetHis.setWorkEfficiency(avgRunningEfficiency);
      targetHis.setWorkEfficiencyExcellent(excellentRunningEfficiency);
      targetHis.setWorkEfficiencyWrong(passRunningEfficiency);
      targetHis.setTransportEfficiency(avgTransportEfficiency);
      targetHis.setTransportEfficiencyExcellent(excellentTransportEfficiency);
      targetHis.setTransportEfficiencyWrong(passTransportEfficiency);
      targetHis.setAvgAllLoadRate(avgLoadRate);
      targetHis.setAvgAllLoadRateExcellent(excellentLoadRate);
      targetHis.setAvgAllLoadRateWrong(passLoadRate);
      targetHis.setAvgResistance(avgResistance);
      targetHis.setAvgResistanceExcellent(excellentResistance);
      targetHis.setAvgResistanceWrong(passResistance);
      targetHis.setUnLoadRunningTime(emptyLoadRunTime);
      targetHis.setUnLoadPowerConsumptionRate(emptyLoadRunEnergy);
      targetHis.setRunningUnLoadRate(runningNoLoadRate);
      beltRouteTargetHisService.updateById(targetHis);
    }else {
      BeltRouteTargetHis targetHisNew = new BeltRouteTargetHis();
      targetHisNew.setFlowNo(flowNo);
      targetHisNew.setTonPowerConsumption(avgTonPowerConsumption);
      targetHisNew.setTonPowerConsumptionExcellent(excellentTonPowerConsumption);
      targetHisNew.setTonPowerConsumptionWrong(passTonPowerConsumption);
      targetHisNew.setWorkEfficiency(avgRunningEfficiency);
      targetHisNew.setWorkEfficiencyExcellent(excellentRunningEfficiency);
      targetHisNew.setWorkEfficiencyWrong(passRunningEfficiency);
      targetHisNew.setTransportEfficiency(avgTransportEfficiency);
      targetHisNew.setTransportEfficiencyExcellent(excellentTransportEfficiency);
      targetHisNew.setTransportEfficiencyWrong(passTransportEfficiency);
      targetHisNew.setAvgAllLoadRate(avgLoadRate);
      targetHisNew.setAvgAllLoadRateExcellent(excellentLoadRate);
      targetHisNew.setAvgAllLoadRateWrong(passLoadRate);
      targetHisNew.setAvgResistance(avgResistance);
      targetHisNew.setAvgResistanceExcellent(excellentResistance);
      targetHisNew.setAvgResistanceWrong(passResistance);
      targetHisNew.setUnLoadRunningTime(emptyLoadRunTime);
      targetHisNew.setUnLoadPowerConsumptionRate(emptyLoadRunEnergy);
      targetHisNew.setRunningUnLoadRate(runningNoLoadRate);
      beltRouteTargetHisService.save(targetHisNew);
    }
  }


  /**
   * 按负载标志获取5分钟内拆分后的List
   * @param minuteList
   */
  private List<List<BeltPerformanceMinute>> splitBeltMinuteListByLoadStatus(List<BeltPerformanceMinute> minuteList){
    int loadStatus = -1;
    List<List<BeltPerformanceMinute>> minuteListList = new ArrayList<>();
    List<BeltPerformanceMinute> oneCollectMinuteList = new ArrayList<>();
    for (int i = 0; i < minuteList.size()-1; i++ ) {
      if(loadStatus == -1) {
        loadStatus = minuteList.get(i).getLoadStatus();
        oneCollectMinuteList.add(minuteList.get(i));
      }else if(minuteList.get(i).getLoadStatus() == loadStatus){
        oneCollectMinuteList.add(minuteList.get(i));
      }else{
        minuteListList.add(new ArrayList<>(oneCollectMinuteList));
        oneCollectMinuteList.clear();
        loadStatus = minuteList.get(i).getLoadStatus();
        oneCollectMinuteList.add(minuteList.get(i));
      }
      if(i == minuteList.size()-1){
        minuteListList.add(new ArrayList<>(oneCollectMinuteList));
      }
    }
    return minuteListList;
  }

  /**
   * 根据吨料耗电量、运行效率、运输效率评判 能耗效率 的优秀、良好、差
   * @param flowNo
   * @param tonPowerConsumption
   * @param workEfficiency
   * @param transportEfficiency
   * @return
   */
  private String getEnergyEfficiencyByTarget(Short flowNo ,BigDecimal tonPowerConsumption, BigDecimal workEfficiency, BigDecimal transportEfficiency) {

    BeltRouteTargetHis targetHis = beltRouteTargetHisService.getOne(
        new QueryWrapper<BeltRouteTargetHis>().lambda()
            .eq(BeltRouteTargetHis::getFlowNo, flowNo).last("LIMIT 1"));

    if (ObjectUtil.isNull(targetHis)) {
      return "无";
    }else {
      BigDecimal totalScore = BigDecimal.ZERO;
      //吨料耗电量
      if(tonPowerConsumption.compareTo(targetHis.getTonPowerConsumptionExcellent()) >= 0){
        totalScore = totalScore.add(BigDecimal.valueOf(10));
      }else if(tonPowerConsumption.compareTo(targetHis.getTonPowerConsumptionWrong()) >= 0){
        totalScore = totalScore.add(BigDecimal.valueOf(5));
      }
      //运行效率
      if(workEfficiency.compareTo(targetHis.getWorkEfficiencyExcellent()) >= 0){
        totalScore = totalScore.add(BigDecimal.valueOf(10));
      }else if(workEfficiency.compareTo(targetHis.getWorkEfficiencyWrong()) >= 0){
        totalScore = totalScore.add(BigDecimal.valueOf(5));
      }
      //运输效率
      if(transportEfficiency.compareTo(targetHis.getTransportEfficiencyExcellent()) >= 0){
        totalScore = totalScore.add(BigDecimal.valueOf(10));
      }else if(transportEfficiency.compareTo(targetHis.getTransportEfficiencyWrong()) >= 0){
        totalScore = totalScore.add(BigDecimal.valueOf(5));
      }
      BigDecimal resultScore = totalScore.divide(BigDecimal.valueOf(3), 2, RoundingMode.HALF_UP);
      if(resultScore.compareTo(BeltCloudUtil.ENERGY_EFFICIENCY_EXCELLENT) >= 0){
        return "优";
      }else if(resultScore.compareTo(BeltCloudUtil.ENERGY_EFFICIENCY_MEDIUM) >= 0){
        return "良";
      }else {
        return "差";
      }
    }
  }

}
